package com.heima.comment.service.impl;

import com.heima.apis.user.IUserFeign;
import com.heima.comment.service.ApCommentHotService;
import com.heima.comment.service.ApCommentService;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vo.CommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.threadlocal.ApThreadLocalUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ApCommentServiceImpl implements ApCommentService {

    @Autowired
    private IUserFeign userFeign;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //1.判断参数
        if(dto==null || dto.getArticleId()==null || dto.getArticleId()==0 || StringUtils.isEmpty(dto.getContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.判断用户是否登录
        ApUser apUser = ApThreadLocalUtils.getUser();
        if(apUser==null || apUser.getId()==0){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //3.调用feign查询用户是否存在
        ApUser apUserDB = userFeign.findById(apUser.getId());
        if(apUserDB==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户不存在");
        }

        //TODO 4.调用feign查询文章是否存在

        //5.判断评论内容是否超140字
        if(dto.getContent().length()>140){
            return ResponseResult.errorResult(AppHttpCodeEnum.LOGIC_ERROR, "文字超限");
        }

        //TODO 6.安全过滤（DFA+阿里云文本审核）

        //7.保存评论
        ApComment apComment = new ApComment();
        apComment.setObjectId(dto.getArticleId());//文章ID
        apComment.setType((short)0);//0-文章 1-动态
        apComment.setUserId(apUserDB.getId());// 用户ID
        apComment.setUserName(apUserDB.getName());// 用户名称
        apComment.setImage(apUserDB.getImage());//用户头像
        apComment.setContent(dto.getContent()); //评论内容
        apComment.setLikes(0);//点赞数0
        apComment.setReply(0);//回复数0
        apComment.setFlag((short)0);//不是热门评论
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        mongoTemplate.save(apComment);//保存评论到MONGO集合中

        //8.响应数据
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Autowired
    private ApCommentHotService apCommentHotService;


    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //1.判断参数
        if(dto==null || StringUtils.isEmpty(dto.getCommentId()) || dto.getOperation()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.判断用户是否登录
        ApUser apUser = ApThreadLocalUtils.getUser();
        if(apUser==null || apUser.getId()==0){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //3.调用feign查询用户是否存在
        ApUser apUserDB = userFeign.findById(apUser.getId());
        if(apUserDB==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户不存在");
        }

        //4.判断评论是否存在
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if(apComment==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "评论不存在");
        }

        //5.如果当前操作点赞，点赞数自增1并保存点赞记录
        if(dto.getOperation()==0){

            //点赞数原子自增
            mongoTemplate.findAndModify(Query.query(Criteria.where("_id").is(dto.getCommentId())),new Update().inc("likes",1),ApComment.class);

            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setUserId(apUser.getId());//用户ID
            apCommentLike.setCommentId(dto.getCommentId());//评论ID
            apCommentLike.setOperation(dto.getOperation()); //0-点赞 1-取消点赞
            mongoTemplate.save(apCommentLike);//保存点赞记录到MONGO集合中


            apComment = mongoTemplate.findById(dto.getCommentId(),ApComment.class);
            //计算热点评论的入口：点赞数大于5且非热点评论
            if(apComment.getLikes()>5 && apComment.getFlag()==0){
                //调用异步计算热点评论的任务
                apCommentHotService.computeHotComment(apComment);
            }
        } else {
            //6.如果当前操作取消点赞，点赞数自减1并更新点赞记录

            //点赞数原子自减
            mongoTemplate.findAndModify(Query.query(Criteria.where("_id").is(dto.getCommentId())),new Update().inc("likes",-1),ApComment.class);


            //更新点赞记录
            Query query = Query.query(Criteria.
                    where("userId").is(apUser.getId()).
                    and("commentId").is(dto.getCommentId()));
            mongoTemplate.upsert(query, new Update().set("operation",dto.getOperation()), ApCommentLike.class);

        }

        //7.封装点赞数并响应数据
        apComment = mongoTemplate.findById(dto.getCommentId(),ApComment.class);

        Map map = new HashMap<>();
        map.put("likes", apComment.getLikes()); //获取最新的点赞数

        return ResponseResult.okResult(map);
    }


    @Override
    public ResponseResult load(CommentDto dto) {
        //1.判断参数
        if(dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }


        //2.查询评论列表
        int size = 10; //默认每页查询10条
        List<ApComment> apCommentList = new ArrayList<>();

        //如果请来自于首页，那么评论由两部分构成（前5条热点评论+剩下5条普通评论）
        if(dto.getIndex()==1){
            //查询5条热点评论列表 （查询条件：文章ID、最小时间、热点的    结果：点赞数倒排，限制5条）
            Criteria criteria1 = Criteria.where("objectId").is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate()).and("flag").is(1);
            List<ApComment> apCommentHotList = mongoTemplate.find(Query.query(criteria1).with(Sort.by(Sort.Direction.DESC, "likes")).limit(5), ApComment.class);
            apCommentList.addAll(apCommentHotList);

            //再查询剩下的普通评论列表（查询条件：文章ID、最小时间、非热点的    结果：时间倒排，限制条数=10-实际查到的热点评论列表条数）
            Criteria criteria2 = Criteria.where("objectId").is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate()).and("flag").is(0);
            List<ApComment> apCommentCommonList = mongoTemplate.find(Query.query(criteria2).with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(size-apCommentHotList.size()), ApComment.class);
            apCommentList.addAll(apCommentCommonList);


        } else {
            //如果不是来自于首页，那么查询普通评论（查询条件：文章ID、最小时间、非热点的    结果：时间倒排，限制条数10条）
            Criteria criteria = Criteria.where("objectId").is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate()).and("flag").is(0);
            apCommentList = mongoTemplate.find(Query.query(criteria).with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(size), ApComment.class);
        }


        //3.判断用户如果没登录，直接响应评论列表数据
        ApUser apUser = ApThreadLocalUtils.getUser();
        if(apUser==null || apUser.getId()==0){
            return ResponseResult.okResult( apCommentList);
        }


        //4.判断用户如果已登录，处理该用户点赞过的评论标识
        /**
         *
         * 假如当前评论表中有如下数据
         *  commentId  articleId    content
         *  1              A        内容1
         *  2              A        内容2
         *  3              A        内容3
         *  4              A        内容4
         *
         * 同时假设点赞表中有如下数据
         * commentId      userId   operation
         * 1              100        0
         * 2              100        0
         * 3              100        0
         * 4              200        0
         *
         * 现在100这个用户登录，查询评论列表：
         * 最终查询的评论列表中，应该是1、2、3这些评论被当前用户点赞过
         *
         *  实现思路：
         *  1） 按照要求查询A这个文章下所有的评论集合
         *  2)  获取所有评论的ID，将这些ID当做点赞记录集合的查询条件（IN查询），查询到点赞记录集合
         *  3）  遍历评论集合，在遍历过程再遍历点赞记录集合，如果点赞记录的评论ID等于遍历中的某条评论的ID，那么就点赞过，设置标识
         */

        //4.获取该用户的点赞点赞记录（查询条件：当前用户ID、 评论ID集合、操作是点赞）

        //获取评论ID集合
        List<String> apCommentIdList = apCommentList.stream().map(ApComment::getId).collect(Collectors.toList());
        //查询点赞记录集合
        Criteria criteria2 = Criteria.where("userId").is(apUser.getId()).and("commentId").in(apCommentIdList).and("operation").is(0);
        List<ApCommentLike> apCommentLikeList = mongoTemplate.find(Query.query(criteria2), ApCommentLike.class);


        //5.遍历并找出当前用户点赞过的评论
        List<CommentVo> commentVoList = new ArrayList<>();
        for (ApComment apComment : apCommentList) {

            //带有点赞标识的评论
            CommentVo commentVo = new CommentVo();
            BeanUtils.copyProperties(apComment,commentVo);

            for (ApCommentLike apCommentLike : apCommentLikeList) {

                //找到被当前用户点赞过的评论
                if(apCommentLike.getCommentId().equals(apComment.getId())){
                    //设置点赞标识
                    commentVo.setOperation((short)0);
                    break;
                }
            }

            commentVoList.add(commentVo);
        }

        //5.响应数据
        return ResponseResult.okResult(commentVoList);
    }
}
